<template>
  <a-modal
    class="image-cropper"
    v-model:open="visible"
    :footer="false"
    @cancel="closeModal"
    :maskClosable="false"
    :width="800"
  >
    <template #title>
          <h3 style="font-weight: bold; font-size: 22px">图片裁剪</h3>
    </template>
    <!-- 裁剪区域 -->
    <div class="cropper-container">
      <vue-cropper
        ref="cropperRef"
        :img="imageUrl"
        :autoCrop="true"
        :fixedBox="false"
        :centerBox="true"
        :can-move="false"
        :canMoveBox="true"
        :info="true"
        outputType="png"
        class="cropper-content"
      />
    </div>

    <!-- 协同编辑操作 -->
    <div class="image-edit-actions" v-if="isTeamSpace">
      <a-space>
        <a-button v-if="editingUser" class="action-btn" disabled> {{ editingUser.userName }}正在进行编辑</a-button>
        <a-button v-if="canEnterEdit" class="action-btn" type="primary" ghost @click="enterEdit">进入编辑</a-button>
        <a-button v-if="canExitEdit" class="action-btn" danger ghost @click="exitEdit">退出编辑</a-button>
      </a-space>
    </div>


    <!-- 操作按钮区域 -->
    <div class="image-cropper-actions">
      <a-space size="middle">
        <a-button
          :disabled="!canEditPicture"
          @click="rotateLeft"
          class="action-btn"
        >
          向左旋转
        </a-button>
        <a-button
          :disabled="!canEditPicture"
          @click="rotateRight"
          class="action-btn"
        >
          向右旋转
        </a-button>
        <a-button
          :disabled="!canEditPicture"
          @click="changeScale(1)"
          class="action-btn"
        >
          放大
        </a-button>
        <a-button
          :disabled="!canEditPicture"
          @click="changeScale(-1)"
          class="action-btn"
        >
          缩小
        </a-button>
        <a-button
          :disabled="!canEditPicture"
          type="primary"
          :loading="loading"
          @click="handleConfirm"
          class="confirm-btn"
        >
          确认
        </a-button>
      </a-space>
    </div>
  </a-modal>
</template>

<script setup lang="ts">
import { computed, onUnmounted, ref, watchEffect } from 'vue'
import { uploadPictureUsingPost } from '@/api/pictureController'
import { message } from 'ant-design-vue'
import { useLoginUserStore } from '@/stores/userLogin'
import PictureEditWebSocket from '@/util/pictureEditWebSocket'
import { PICTURE_EDIT_ACTION_ENUM, PICTURE_EDIT_MESSAGE_TYPE_ENUM } from '@/constants/picture'
import { SPACE_TYPE_ENUM } from '@/constants/space'

// 父组件传入的参数
interface Props {
  imageUrl?: string
  picture?: API.PictureVO
  spaceId?: number
  space?: API.SpaceVO
  onSuccess?: (newPicture: API.PictureVO) => void
}

const props = defineProps<Props>()

// 判断是否是团队空间
const isTeamSpace = computed(() => {
  return props.space?.spaceType === SPACE_TYPE_ENUM.TEAM
})

// 编辑器组件的引用
const cropperRef = ref()

// 向左旋转
const rotateLeft = () => {
  cropperRef.value.rotateLeft()
  editPicture(PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT)
}

// 向右旋转
const rotateRight = () => {
  cropperRef.value.rotateRight()
  editPicture(PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT)
}

// 缩放
const changeScale = (num: number) => {
  cropperRef.value.changeScale(num)
  if(num > 0){
    editPicture(PICTURE_EDIT_ACTION_ENUM.ZOOM_IN)
  }else {
    editPicture(PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT)
  }
}

// ----------- 上传修改裁剪修改后的图片 --------------
// 点击确认按钮触发的事件
const loading = ref<boolean>(false)
// 确认裁剪
const handleConfirm = () => {
  cropperRef.value.getCropBlob((blob: Blob) => {
    const fileName = (props.picture?.name || 'image') + '.png'
    const file = new File([blob], fileName, { type: blob.type })
    // 上传图片
    handleUpload({ file })
  })
}

/**
 * 上传 (裁剪修改后的图片进行覆盖)
 * @param file
 */
const handleUpload = async ({ file }: any) => {
  loading.value = true
  try {
    const params: API.PictureUploadDTO = props.picture ? { id: props.picture.id } : {}
    params.spaceId = props.spaceId
    const res = await uploadPictureUsingPost(params, {}, file)
    // @ts-ignore
    if (res.data?.code === 0 && res.data.data) {
      message.success('操作成功')
      // 将上传成功的图片信息传递给父组件
      // @ts-ignore
      props.onSuccess?.(res.data.data)
      closeModal();
    } else {
      // @ts-ignore
      message.error('操作失败，' + res.data.message)
    }
  } catch (error) {
    message.error('图片上传失败')
  } finally {
    loading.value = false
  }
}


// ------ 模态框区域 ----------
// 是否可见
const visible = ref(false)

// 打开弹窗
const openModal = () => {
  visible.value = true
}

// 关闭弹窗
const closeModal = () => {
  visible.value = false
  // 在模态框关闭时，也要关闭 WebSocket 连接
  // 断开与 WebSocket 的连接
  if(webSocket){
    webSocket?.disconnect();
  }
  // 设置当前编辑用户为空
  editingUser.value = undefined
}

// 暴露函数给父组件
defineExpose({
  openModal,
})

// --------- 团队实时编辑 ------------
// 获取当前登录用户
const loginUserStore = useLoginUserStore();
const loginUser = loginUserStore.loginUser;
// 定义当前正在编辑的用户
const editingUser = ref<API.UserVO>();
// 定义显示按钮的权限
// 没有人在编辑时，才能加入编辑
const canEnterEdit = computed(() => {
    return !editingUser.value;
})
// 当前登录用户是在编辑的用户，才能编辑
const canEditPicture = computed(() => {
  // 如果不是团队空间，默认允许编辑
  if(!isTeamSpace.value){
    return true;
  }
  return loginUser.id === editingUser.value?.id;
})
// 当前编辑用户是当前登录用户，才能退出编辑
const canExitEdit = computed(() => {
  return loginUser.id === editingUser.value?.id;
})

// 定义 WebSocket 实例
let webSocket: PictureEditWebSocket | null;

// 初始化 WebSocket 连接
const initWebSocket = () => {
  // 判断当前是否需要初始化 WebSocket
  const pictureId = props.picture?.id;
  if(!pictureId || visible.value === false){
    return;
  }

  // 判断之前的 WebSocket 实例是否销毁
  if(webSocket){
    webSocket.disconnect();
  }

  //新建 WebSocket 实例
  webSocket = new PictureEditWebSocket(pictureId)
  // 建立连接
  webSocket.connect()

  // 监听各种事件
  // 监听发送消息
  webSocket?.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.INFO, (msg) => {
    console.log('收到消息通知：', msg);
    message.info(msg.message);
  })
  // 监听错误消息
  webSocket?.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ERROR, (msg) => {
    console.log('收到错误消息：', msg);
    message.error(msg.message);
  })
  // 监听进入编辑状态
  webSocket?.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT, (msg) => {
    console.log('收到用户进入编辑状态消息：', msg);
    message.info(msg.message);
    // 设置当前编辑用户
    editingUser.value = msg.user;
  })
  // 监听执行编辑操作的状态
  webSocket?.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION, (msg) => {
    console.log('收到用户进行编辑消息：', msg);
    message.info(msg.message);
    switch (msg.editAction){
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_IN:
        cropperRef.value.changeScale(1)
        break;
      case PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT:
        cropperRef.value.changeScale(-1)
        break;
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT:
        cropperRef.value.rotateLeft()
        break;
      case PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT:
        cropperRef.value.rotateRight()
        break;
    }
  })
  // 监听用户退出编辑状态
  // 监听进入编辑状态
  webSocket?.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT, (msg) => {
    console.log('收到用户退出编辑状态消息：', msg);
    message.info(msg.message);
    // 设置当前编辑用户为空
    editingUser.value = undefined
  })
}

// 监听事件变量的变化，触发初始化 WebSocket
watchEffect(() => {
  // 如果不是团队空间，不初始化 WebSocket
  if(isTeamSpace.value){
    initWebSocket();
  }
})

// 在页面销毁时销毁 WebSocket
onUnmounted(() => {
  // 断开与 WebSocket 的连接
  if(webSocket){
    webSocket?.disconnect();
  }
  // 设置当前编辑用户为空
  editingUser.value = undefined
})

// 定义编辑操作按钮的点击事件
// 进入编辑
const enterEdit = () => {
  if(webSocket){
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT,
    })
  }
}
// 退出编辑
const exitEdit = () => {
  if(webSocket){
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT,
    })
  }
}
// 编辑图片时
const editPicture = (action: string) => {
  if(webSocket){
    webSocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION,
      editAction: action
    })
  }
}
</script>

<style scoped>
.image-cropper {
  text-align: center;
  padding: 16px 0;
}

/* 裁剪区域样式 */
.cropper-container {
  margin: 0 auto 24px;
  width: 90%;
  max-width: 600px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  padding: 16px;
  background-color: #fff;
  transition: all 0.3s ease;
}

.cropper-content {
  height: 400px !important;
  border-radius: 12px;
  overflow: hidden;
}

/* 编辑操作区域样式 */
.image-edit-actions{
  margin-bottom: 12px;
  display: flex;
  justify-content: center;
}

/* 按钮区域样式 */
.image-cropper-actions {
  padding: 12px 0;
  display: flex;
  justify-content: center;
}

/* 普通按钮样式 */
.action-btn {
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
  border-radius: 4px;
}

.action-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}

/* 确认按钮样式 */
.confirm-btn {
  box-shadow: 0 2px 6px rgba(76, 175, 80, 0.4);
  transition: all 0.3s ease;
  border-radius: 4px;
}

.confirm-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 10px rgba(76, 175, 80, 0.4);
}

/* 响应式调整 */
@media (max-width: 768px) {
  .cropper-container {
    width: 95%;
    padding: 8px;
  }

  .cropper-content {
    height: 300px !important;
  }

  .image-cropper-actions {
    padding: 8px;
  }

  .action-btn, .confirm-btn {
    padding: 4px 12px;
    font-size: 13px;
  }
}
</style>
